use axum::{http::Method, middleware::from_fn_with_state, routing::post, Router};
use tower_http::cors::{self, CorsLayer};

use crate::{
    app_state::AppState,
    errors::error::AppError,
    handlers::user_handlers::{signin_handler, signup_handler},
    middlewares::{set_layer, verify_token},
    openapi::OpenApiRouter,
};

pub mod user_routes;

pub async fn get_router(app_state: AppState) -> Result<Router, AppError> {
    let cors = CorsLayer::new()
        // allow `GET` and `POST` when accessing the resource
        .allow_methods([
            Method::GET,
            Method::POST,
            Method::PATCH,
            Method::DELETE,
            Method::PUT,
        ])
        .allow_origin(cors::Any)
        .allow_headers(cors::Any);
    let user_router = user_routes::get_user_routes(app_state.clone());
    let api = Router::new()
        .nest("/users", user_router)
        .layer(from_fn_with_state(
            app_state.clone(),
            verify_token::<AppState>,
        ))
        .route("/signin", post(signin_handler))
        .route("/signup", post(signup_handler))
        .layer(cors);
    let state = app_state.clone();
    let app = Router::new().openapi().nest("/api", api).with_state(state);
    Ok(set_layer(app))
}
